package top.chmin.project.cloud.builder;

import org.springframework.stereotype.Component;
import top.chmin.project.cloud.common.entity.column.auto.EntityColumn;
import top.chmin.project.cloud.common.entity.label.value.auto.EntityLabelValue;

/**
 * chmin
 * 2023/12/15 15:21
 * cloud-builder
 */
@Component
public class PluginBuilder implements Builder {
    @Override
    public void build(BuilderConfig config) {
        String content = """
                package top.chmin.project.cloud.#e.module#.#e.pack#.auto;
                                
                // field import auto
                                
                import cn.hutool.json.JSONUtil;
                import lombok.extern.slf4j.Slf4j;
                import org.springframework.stereotype.Component;
                import top.chmin.project.cloud.common.entity.Page;
                import top.chmin.project.cloud.common.tool.DatetimeTool;
                import top.chmin.project.cloud.common.tool.LocalTool;
                import top.chmin.project.cloud.common.column.code.auto.ColumnCodeService;
                                
                import java.time.LocalDateTime;
                                
                /**
                 * chmin
                 * #dateTime#
                 * cloud-builder
                 */
                @Slf4j
                @Component
                public class #e.simpleName#Plugin {
                                
                    @Resource
                    CodeRecordService codeRecordService;
                    
                    public void checkSave(#e.simpleName#Save.Param param) {
                        log.debug("checkSave-param: {}", JSONUtil.toJsonStr(param));
                        if (param == null) {
                            throw new RuntimeException("保存对象不能为空");
                        }
                    }
                    
                    public void beforeSave(#e.simpleName# #e.fieldName#) {
                        log.debug("beforeSave-#e.fieldName#: {}", JSONUtil.toJsonStr(#e.fieldName#));
                        #e.fieldName#.setCreateBy(LocalTool.getUserId());
                        #e.fieldName#.setUpdateBy(LocalTool.getUserId());
                        #e.fieldName#.setCreateTime(LocalDateTime.now());
                        #e.fieldName#.setUpdateTime(LocalDateTime.now());
                // field code auto
                    }
                    
                    public void afterSave(#e.simpleName#Save.Param param, #e.simpleName# #e.fieldName#, int result) {
                        log.debug("afterSave-param: {}", JSONUtil.toJsonStr(param));
                        log.debug("afterSave-#e.fieldName#: {}", JSONUtil.toJsonStr(#e.fieldName#));
                        log.debug("afterSave-result: {}", JSONUtil.toJsonStr(result));
                        
                    }
                                
                    public void checkUpdateById(#e.simpleName#UpdateById.Param param) {
                        log.debug("checkUpdateById-param: {}", JSONUtil.toJsonStr(param));
                        if (param == null) {
                            throw new RuntimeException("更新对象不能为空");
                        }
                        if (param.getId() == null) {
                            throw new RuntimeException("更新对象id不能为空");
                        }
                    }
                    
                    public void beforeUpdateById(#e.simpleName# #e.fieldName#) {
                        log.debug("beforeUpdateById-#e.fieldName#: {}", JSONUtil.toJsonStr(#e.fieldName#));
                        #e.fieldName#.setUpdateBy(LocalTool.getUserId());
                        #e.fieldName#.setUpdateTime(LocalDateTime.now());
                    }
                    
                    public void afterUpdateById(#e.simpleName#UpdateById.Param param, #e.simpleName# #e.fieldName#, int result) {
                        log.debug("afterUpdateById-param: {}", JSONUtil.toJsonStr(param));
                        log.debug("afterUpdateById-#e.fieldName#: {}", JSONUtil.toJsonStr(#e.fieldName#));
                        log.debug("afterUpdateById-result: {}", JSONUtil.toJsonStr(result));
                        
                    }
                    
                    public void checkDeleteById(#e.simpleName#DeleteById.Param param) {
                        log.debug("checkDeleteById-param: {}", JSONUtil.toJsonStr(param));
                        if (param == null) {
                            throw new RuntimeException("删除对象不能为空");
                        }
                        if (param.getId() == null) {
                            throw new RuntimeException("删除对象id不能为空");
                        }
                    }
                    
                    public void afterDeleteById(#e.simpleName#DeleteById.Param param, int result) {
                        log.debug("afterDeleteById-param: {}", JSONUtil.toJsonStr(param));
                        log.debug("afterDeleteById-result: {}", JSONUtil.toJsonStr(result));
                        
                    }
                                
                    public void checkSelectById(#e.simpleName#SelectById.Param param) {
                        log.debug("checkSelectById-param: {}", JSONUtil.toJsonStr(param));
                        if (param == null) {
                            throw new RuntimeException("查询对象不能为空");
                        }
                        if (param.getId() == null) {
                            throw new RuntimeException("查询对象id不能为空");
                        }
                    }
                    
                    public void beforeSelectById(#e.simpleName#SelectById.Param param, #e.simpleName#FPC fpc) {
                        log.debug("beforeSelectById-param: {}", JSONUtil.toJsonStr(param));
                        
                    }
                    
                    public void afterSelectById(#e.simpleName#SelectById.Param param, #e.simpleName#SelectById.Result result) {
                        log.debug("afterSelectById-param: {}", JSONUtil.toJsonStr(param));
                        log.debug("afterSelectById-result: {}", JSONUtil.toJsonStr(result));
                        
                    }
                                
                    public void checkSelectPage(#e.simpleName#SelectPage.Param param) {
                        log.debug("checkSelectPage-param: {}", JSONUtil.toJsonStr(param));
                        if (param == null) {
                            throw new RuntimeException("分页对象不能为空");
                        }
                    }
                    
                    public void beforeSelectPage(#e.simpleName#SelectPage.Param param, #e.simpleName#FPC fpc) {
                        log.debug("beforeSelectPage-param: {}", JSONUtil.toJsonStr(param));
                // field beforeSelectPage auto
                    }
                    
                    public void afterSelectPage(#e.simpleName#SelectPage.Param param, Page<#e.simpleName#SelectPage.Result> result) {
                        log.debug("afterSelectPage-param: {}", JSONUtil.toJsonStr(param));
                        log.debug("afterSelectPage-result: {}", JSONUtil.toJsonStr(result));
                        
                    }
                                
                // entity select auto
                                
                // entity search auto
                }
                """;

        save(config, config.getEntity().getClassName() + "Plugin", content, false);


        config.getEntityColumnList()
                .forEach(f -> appendJava(config, f,
                        "// field import auto",
                        "import java.util.List;",
                        "import java.util.List;",
                        config.getEntity().getClassName() + "Plugin"));

        config.getEntityColumnList()
                .stream()
                .filter(f -> !"id".equals(f.getFieldName()))
                .forEach(f -> {

                    if ("LocalDateTime".equals(f.getSimpleType())) {
                        appendJava(config, f,
                                "// field beforeSelectPage auto",
                                "fpc.#f.fieldName#().ge(param.get#f.methodName#() == null || param.get#f.methodName#().length == 0 ? null : param.get#f.methodName#()[0]);",
                                """
                                        fpc.#f.fieldName#().ge(param.get#f.methodName#() == null || param.get#f.methodName#().length == 0 ? null : param.get#f.methodName#()[0]);
                                        fpc.#f.fieldName#().lt(param.get#f.methodName#() == null || param.get#f.methodName#().length < 2 ? null : DatetimeTool.nextDay(param.get#f.methodName#()[1]));""",
                                config.getEntity().getClassName() + "Plugin");
                    } else {
                        appendJava(config, f,
                                "// field beforeSelectPage auto",
                                "fpc.#f.fieldName#().eq(param.get#f.methodName#());",
                                "fpc.#f.fieldName#().eq(param.get#f.methodName#());",
                                config.getEntity().getClassName() + "Plugin");
                    }
                });

        for (EntityLabelValue entityLabelValue : config.getEntityLabelValueList()) {
            EntityColumn label = config.getEntityColumnList()
                    .stream().filter(f -> f.getFieldCode().equals(entityLabelValue.getLabelFieldCode()))
                    .findFirst().orElse(null);
            EntityColumn value = config.getEntityColumnList()
                    .stream().filter(f -> f.getFieldCode().equals(entityLabelValue.getValueFieldCode()))
                    .findFirst().orElse(null);
            if (label == null || value == null) {
                continue;
            }

            if ("SELECT".equals(entityLabelValue.getDataApiType())) {
                appendJava(config,
                        "// entity select auto",
                        "checkSelect%s".formatted(value.getMethodName()),
                        """
                                    // entity select auto
                                    public void checkSelect%s(#e.simpleName#%sSelect.Param param) {
                                        log.debug("checkSelect%s-param: {}", JSONUtil.toJsonStr(param));
                                    }
                                    
                                    public void beforeSelect%s(#e.simpleName#%sSelect.Param param, #e.simpleName#FPC fpc) {
                                        log.debug("beforeSelect%s-param: {}", JSONUtil.toJsonStr(param));
                                        log.debug("beforeSelect%s-fpc: {}", JSONUtil.toJsonStr(fpc));
                                    
                                    }
                                    
                                    public void afterSelect%s(#e.simpleName#%sSelect.Param param, List<#e.simpleName#%sSelect.Result> result) {
                                        log.debug("afterSelect%s-param: {}", JSONUtil.toJsonStr(param));
                                        log.debug("afterSelect%s-result: {}", JSONUtil.toJsonStr(result));
                                    
                                    }
                                """.formatted(
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName()
                        ),
                        config.getEntity().getClassName() + "Plugin");
            }

            if ("SEARCH".equals(entityLabelValue.getDataApiType())) {
                appendJava(config,
                        "// entity search auto",
                        "checkSearch%s".formatted(value.getMethodName()),
                        """
                                    // entity search auto
                                    public void checkSearch%s(#e.simpleName#%sSearch.Param param) {
                                        log.debug("checkSearch%s-param: {}", JSONUtil.toJsonStr(param));
                                    }
                                    
                                    public void beforeSearch%s(#e.simpleName#%sSearch.Param param, #e.simpleName#FPC fpc) {
                                        log.debug("beforeSearch%s-param: {}", JSONUtil.toJsonStr(param));
                                        log.debug("beforeSearch%s-fpc: {}", JSONUtil.toJsonStr(fpc));
                                    
                                    }
                                    
                                    public void afterSearch%s(#e.simpleName#%sSearch.Param param, List<#e.simpleName#%sSearch.Result> result) {
                                        log.debug("afterSearch%s-param: {}", JSONUtil.toJsonStr(param));
                                        log.debug("afterSearch%s-result: {}", JSONUtil.toJsonStr(result));
                                    
                                    }
                                """.formatted(
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName(),
                                value.getMethodName()
                        ),
                        config.getEntity().getClassName() + "Plugin");
            }

        }

        config.getColumnCodeList().forEach(cc -> {
            EntityColumn entityColumn = config.getEntityColumnList()
                    .stream().filter(f -> f.getFieldCode().equals(cc.getFieldCode()))
                    .findFirst().orElseThrow();
            appendJava(config,
                    "// field code auto",
                    "#e.fieldName#.set%s(codeRecordService.getCode(\"%s\"));".formatted(
                            entityColumn.getMethodName(),
                            cc.getCodeName()
                    ),
                    "#e.fieldName#.set%s(codeRecordService.getCode(\"%s\"));".formatted(
                            entityColumn.getMethodName(),
                            cc.getCodeName()
                    ),
                    config.getEntity().getClassName() + "Plugin");
        });
    }
}
